package com.ytjj.qmyx.admin.service.imService.impl;

import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Maps;
import com.ytjj.common.api.CommonPage;
import com.ytjj.common.api.CommonResult;
import com.ytjj.common.constants.QueueConstants;
import com.ytjj.common.constants.im.ImRedisKeyConstant;
import com.ytjj.common.exception.ApiException;
import com.ytjj.common.service.RedisService;
import com.ytjj.qmyx.admin.eunm.im.YxImServiceUserStatusEnum;
import com.ytjj.qmyx.admin.eunm.im.YxImSessionStatusEnum;
import com.ytjj.qmyx.admin.mapper.*;
import com.ytjj.qmyx.admin.model.*;
import com.ytjj.qmyx.admin.model.dto.*;
import com.ytjj.qmyx.admin.model.request.im.ImMonitorListRequest;
import com.ytjj.qmyx.admin.model.request.im.ImRealTimeServiceDateListRequest;
import com.ytjj.qmyx.admin.model.request.im.ImSessionInfoRequest;
import com.ytjj.qmyx.admin.model.request.im.ImWorkReportListRequest;
import com.ytjj.qmyx.admin.model.response.im.*;
import com.ytjj.qmyx.admin.model.vo.ImSessionInfoVO;
import com.ytjj.qmyx.admin.service.imService.ImLeaveMsgService;
import com.ytjj.qmyx.admin.service.imService.ImSessionInfoService;
import com.ytjj.qmyx.admin.utils.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ImSessionInfoServiceImpl implements ImSessionInfoService {

    @Resource
    private ImSessionInfoMapper imSessionInfoMapper;

    @Resource
    private ImMessageInfoMapper imMessageInfoMapper;

    @Resource
    private ImCustomerLabelMapper imCustomerLabelMapper;

    @Resource
    private ImUserBindInfoMapper imUserBindInfoMapper;

    @Autowired
    private RedisService redisService;

    @Resource
    private ImServiceUserMapper imServiceUserMapper;
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ImLeaveMsgService imLeaveMsgService;



    /**
     * 获取该客服的客户列表
     * @param
     * @return
     */
    @Override
    public CustomerListDto getCustomerList(String serviceId, Integer sessionId) {
        CustomerListDto customerListDto = new CustomerListDto();
        //先查全部会话(根据客服email取该客户最新的会话)(只查询当天的会话)
        List<ImSessionInfoDto> allSession = imSessionInfoMapper.selectAllByServiceId(serviceId);
        if (CollectionUtils.isEmpty(allSession)){
            return new CustomerListDto();
        }
        if (null != sessionId) {
            allSession.stream().forEach(item -> {
                if (sessionId.equals(item.getId())) {
                    item.setCurSel(1);
                    return;
                }
            });
        }
        //根据会话状态区分
        List<ImSessionInfoDto> onlineImSessionInfo = allSession.stream().filter(item -> 1 == item.getStatus()).collect(Collectors.toList());//聊天中
        List<ImSessionInfoDto> offlineImSessionInfo = allSession.stream().filter(item -> 3 == item.getStatus()).collect(Collectors.toList());//离线
        List<ImSessionInfoDto> endImSessionInfo = allSession.stream().filter(item -> 2 == item.getStatus()).collect(Collectors.toList());//已结束

//        List<Integer> sessionIds = allSession.stream().map(ImSessionInfoDto::getId).collect(Collectors.toList());
//        if (CollectionUtils.isEmpty(sessionIds)) {
//            return customerListDto;
//        }

//        List<ImMessageInfo> imMessageInfoList = imMessageInfoMapper.selectBySessionIds(sessionIds);
        onlineImSessionInfo.stream().forEach(item -> {
            //返回用户标签
            ImUserBindInfoDto imUserBindInfoDto = getImUserBindInfo(item.getCustomerId());
            if (null != imUserBindInfoDto){
                ImCustomerLabel imCustomerLabel = getImCustomerLabel(imUserBindInfoDto.getUserLabel());
                if(null !=imCustomerLabel){
                    item.setUserLabel(imCustomerLabel.getLabelName());
                    item.setColor(imCustomerLabel.getLabelColour());
                }
            }
            //查询当前会话最新的一条消息
            ImMessageInfo imMessageInfo = imMessageInfoMapper.selectBySessionId(item.getId());
//            List<ImMessageInfo> imMessageInfosBySessionId = imMessageInfoList.stream().filter(s -> item.getId().equals(s.getSessionId())).collect(Collectors.toList());
//            imMessageInfosBySessionId = imMessageInfosBySessionId.stream().sorted(Comparator.comparing(ImMessageInfo::getCreateTime)).collect(Collectors.toList());
//            ImMessageInfo imMessageInfo = null;
//            if (!CollectionUtils.isEmpty(imMessageInfosBySessionId)) {
//                imMessageInfo = imMessageInfosBySessionId.get(0);
//            }
            item.setNoReadNum(0);
            if (null !=imMessageInfo){
                item.setMessage(imMessageInfo.getContent());
                item.setMessageTime(imMessageInfo.getCreateTime());
                if (item.getId().equals(sessionId)) {
                    item.setNoReadNum(0);
                }else {
                    item.setNoReadNum(null == imMessageInfo.getNoReadNum() ? 0 : imMessageInfo.getNoReadNum());
                }
            }
        });
        offlineImSessionInfo.stream().forEach(item -> {
            //返回用户标签
//            ImUserBindInfoDto imUserBindInfoDto = imUserBindInfoMapper.selectOneByCustomerId(item.getCustomerId());
            ImUserBindInfoDto imUserBindInfoDto = getImUserBindInfo(item.getCustomerId());
            if (null != imUserBindInfoDto){
//                ImCustomerLabel imCustomerLabel = imCustomerLabelMapper.selectOne(imUserBindInfoDto.getUserLabel());
                ImCustomerLabel imCustomerLabel = getImCustomerLabel(imUserBindInfoDto.getUserLabel());
                if(null !=imCustomerLabel){
                    item.setUserLabel(imCustomerLabel.getLabelName());
                    item.setColor(imCustomerLabel.getLabelColour());
                }
            }
            ImMessageInfo imMessageInfo = imMessageInfoMapper.selectBySessionId(item.getId());
//            List<ImMessageInfo> imMessageInfosBySessionId = imMessageInfoList.stream().filter(s -> item.getId().equals(s.getSessionId())).collect(Collectors.toList());
//            imMessageInfosBySessionId = imMessageInfosBySessionId.stream().sorted(Comparator.comparing(ImMessageInfo::getCreateTime)).collect(Collectors.toList());
//            ImMessageInfo imMessageInfo = null;
//            if (!CollectionUtils.isEmpty(imMessageInfosBySessionId)) {
//                imMessageInfo = imMessageInfosBySessionId.get(0);
//            }
            item.setNoReadNum(0);
            if (null !=imMessageInfo){
                item.setMessage(imMessageInfo.getContent());
                item.setMessageTime(imMessageInfo.getCreateTime());
                item.setNoReadNum(null == imMessageInfo.getNoReadNum() ? 0 : imMessageInfo.getNoReadNum());
            }
        });
        //只返回有消息的会话
//        offlineImSessionInfo = offlineImSessionInfo.stream().filter(item -> null != item.getMessage()).collect(Collectors.toList());
        endImSessionInfo.stream().forEach(item -> {
            //返回用户标签
//            ImUserBindInfoDto imUserBindInfoDto = imUserBindInfoMapper.selectOneByCustomerId(item.getCustomerId());
            ImUserBindInfoDto imUserBindInfoDto = getImUserBindInfo(item.getCustomerId());
            if (null != imUserBindInfoDto){
//                ImCustomerLabel imCustomerLabel = imCustomerLabelMapper.selectOne(imUserBindInfoDto.getUserLabel());
                ImCustomerLabel imCustomerLabel = getImCustomerLabel(imUserBindInfoDto.getUserLabel());
                if(null !=imCustomerLabel){
                    item.setUserLabel(imCustomerLabel.getLabelName());
                    item.setColor(imCustomerLabel.getLabelColour());
                }
            }
            ImMessageInfo imMessageInfo = imMessageInfoMapper.selectBySessionId(item.getId());
//            List<ImMessageInfo> imMessageInfosBySessionId = imMessageInfoList.stream().filter(s -> item.getId().equals(s.getSessionId())).collect(Collectors.toList());
//            imMessageInfosBySessionId = imMessageInfosBySessionId.stream().sorted(Comparator.comparing(ImMessageInfo::getCreateTime)).collect(Collectors.toList());
//            ImMessageInfo imMessageInfo = null;
//            if (!CollectionUtils.isEmpty(imMessageInfosBySessionId)) {
//                imMessageInfo = imMessageInfosBySessionId.get(0);
//            }
            item.setNoReadNum(0);
            if (null !=imMessageInfo){
                item.setMessage(imMessageInfo.getContent());
                item.setMessageTime(imMessageInfo.getCreateTime());
                item.setNoReadNum(null == imMessageInfo.getNoReadNum() ? 0 : imMessageInfo.getNoReadNum());
            }
        });
        //只返回有消息的会话
//        endImSessionInfo = endImSessionInfo.stream().filter(item -> null != item.getMessage()).collect(Collectors.toList());

        onlineImSessionInfo = onlineImSessionInfo.stream().sorted((stu1, stu2) ->
                Long.compare(null == stu2.getNoReadNum() ? 0 : stu2.getNoReadNum(), null == stu1.getNoReadNum() ? 0 : stu1.getNoReadNum()))
                .sorted((stu1, stu2) ->
                    Long.compare(null == stu2.getMessageTime() ? 0L : stu2.getMessageTime().getTime(), null == stu1.getMessageTime() ? 0L : stu1.getMessageTime().getTime()))
                .collect(Collectors.toList());
        offlineImSessionInfo = offlineImSessionInfo.stream().sorted((stu1, stu2) ->
                Long.compare(null == stu2.getNoReadNum() ? 0 : stu2.getNoReadNum(), null == stu1.getNoReadNum() ? 0 : stu1.getNoReadNum()))
                .sorted((stu1, stu2) ->
                        Long.compare(null == stu2.getMessageTime() ? 0L : stu2.getMessageTime().getTime(), null == stu1.getMessageTime() ? 0L : stu1.getMessageTime().getTime()))
                .collect(Collectors.toList());
        endImSessionInfo = endImSessionInfo.stream().sorted((stu1, stu2) ->
                Long.compare(null == stu2.getNoReadNum() ? 0 : stu2.getNoReadNum(), null == stu1.getNoReadNum() ? 0 : stu1.getNoReadNum()))
                .sorted((stu1, stu2) ->
                        Long.compare(null == stu2.getMessageTime() ? 0L : stu2.getMessageTime().getTime(), null == stu1.getMessageTime() ? 0L : stu1.getMessageTime().getTime()))
                .collect(Collectors.toList());

        customerListDto.setOnlineImSessionInfo(onlineImSessionInfo);
        customerListDto.setOfflineImSessionInfo(offlineImSessionInfo);
        customerListDto.setEndImSessionInfo(endImSessionInfo);
        try {
            if (null != sessionId) {
                imMessageInfoMapper.updateMessageStatusIsRead(sessionId);
            }
        } catch (Exception e) {
            log.error("===更新会话消息状态异常==={}", sessionId);
        }
        return customerListDto;
    }

    private ImUserBindInfoDto getImUserBindInfo(String id) {
        //返回用户标签
        String userBindInfoKey = "admin:im:userbind:" + id;
        String imUserBindInfoRedisVal = redisService.get(userBindInfoKey);
        ImUserBindInfoDto imUserBindInfoDto = null;
        if (StringUtils.isEmpty(imUserBindInfoRedisVal)) {
            imUserBindInfoDto = imUserBindInfoMapper.selectOneByCustomerId(id);
            if (null != imUserBindInfoDto) {
                redisService.set(userBindInfoKey, JSONObject.toJSONString(imUserBindInfoDto));
                redisService.expire(userBindInfoKey, 60);
            }
        }else {
            imUserBindInfoDto = JSONObject.parseObject(imUserBindInfoRedisVal, ImUserBindInfoDto.class);
        }
        return imUserBindInfoDto;
    }

    private ImCustomerLabel getImCustomerLabel(Byte label) {
        String customerLabelKey = "admin:im:customer:label:" + label;
        String customerLabelRedisVal = redisService.get(customerLabelKey);
        ImCustomerLabel imCustomerLabel = null;
        if (StringUtils.isEmpty(customerLabelRedisVal)) {
            imCustomerLabel = imCustomerLabelMapper.selectOne(label);
            if (null != imCustomerLabel) {
                redisService.set(customerLabelKey, JSONObject.toJSONString(imCustomerLabel));
                redisService.expire(customerLabelKey, 600);
            }
        }else {
            imCustomerLabel = JSONObject.parseObject(customerLabelRedisVal, ImCustomerLabel.class);
        }
        return imCustomerLabel;
    }

    /**
     *   根据客户唯一标识获取访问记录
     * @param customerId
     * @return
     */
    @Override
    public ImSessionInfoResponse getAccessRecord(String customerId, Integer id) {
        ImSessionInfoResponse imSessionInfoResponse = new ImSessionInfoResponse();
        List<ImSessionInfoDto> list = imSessionInfoMapper.getAccessRecord(customerId);
        list.stream().forEach(item -> {
            if (null != id && id.equals(item.getId())){
                imSessionInfoResponse.setShowSession(item);
            }
        });
        //只获取有聊天记录的会话返回
        list = list.stream().filter(item ->null != imMessageInfoMapper.selectBySessionId(item.getId())).collect(Collectors.toList());
        //会话的解决状态未标注则全改为已解决
        List<Integer> sessionIds = new ArrayList<>();
        list.stream().forEach(item ->{
            if (null == item.getSolveStatus()){
                sessionIds.add(item.getId());
                item.setSolveStatus(3);
            }
        });
        if (null != sessionIds && sessionIds.size() > 0){
            imUserBindInfoMapper.updateSolveStatusBySessionIds(sessionIds);
        }
        imSessionInfoResponse.setList(list);
        return imSessionInfoResponse;
    }

    /**
     *   条件获取访问记录
     * @param infoVO
     * @return
     */
    @Override
    public CommonPage getAllAccessRecord(ImSessionInfoVO infoVO) {
        PageHelper.startPage(infoVO.getPageNum(), infoVO.getPageSize());
        List<ImSessionInfoDto> imSessionInfoDtoList = imSessionInfoMapper.getAllAccessRecord(infoVO);
        imSessionInfoDtoList.stream().forEach(item ->{
            ImUserBindInfoDto imUserBindInfoDto =imUserBindInfoMapper.selectBySessionId(item.getCustomerId());
            item.setUserName(item.getCustomerId());
            if (null != imUserBindInfoDto && !StringUtils.isEmpty(imUserBindInfoDto.getUserName())){
                item.setUserName(imUserBindInfoDto.getUserName());
            }
        });
        List<Integer> sessionIds = new ArrayList<>();
        //会话的解决状态未标注则全改为已解决
        imSessionInfoDtoList.stream().filter(item -> null == item.getSolveStatus()).forEach(item ->{
            sessionIds.add(item.getId());
        });
        if (!CollectionUtils.isEmpty(sessionIds)){
            imUserBindInfoMapper.updateSolveStatusBySessionIds(sessionIds);
        }
        return CommonPage.restPage(imSessionInfoDtoList);
    }

    /**
     *  更新客户满意度
     * @return
     */
    @Override
    public CommonResult updateSatisfaction(ImSessionInfoVO imSessionInfoVO) {
        int count = imSessionInfoMapper.updateSatisfaction(imSessionInfoVO.getId(),imSessionInfoVO.getSatisfaction());
        if (count > 0) {
            return CommonResult.success();
        }
        return CommonResult.failed("找不到对应的会话信息{" + imSessionInfoVO.getId() + "}");
    }

    @Override
    public ImSessionInfo selectById(Integer sessionId) {
        return imSessionInfoMapper.selectByPrimaryKey(sessionId);
    }

    /**
     * 查询客户信息
     * @param customerId
     * @return
     */
    private List<ImSessionInfo> getImSessionInfos(String customerId) {
        ImSessionInfoExample imSessionInfoExample = new ImSessionInfoExample();
        imSessionInfoExample.createCriteria().andCustomerIdEqualTo(customerId);
        return imSessionInfoMapper.selectByExample(imSessionInfoExample);
    }

    @Override
    public CommonResult sessionTransferByOldObj(ImSessionInfo bean) {
        int count = imSessionInfoMapper.updateByPrimaryKeySelective(bean);
        if (count > 0) {
            return CommonResult.success(count);
        }
        return CommonResult.failed();
    }

    /**
     * 结束会话
     * todo 这里是否需要做结束会话客服id是否和会话绑定的客服id一致的校验
     * @param request
     * @return
     */
    @Override
    public CommonResult finalSession(ImSessionInfoRequest request) {
        ImSessionInfo imSessionInfo = imSessionInfoMapper.selectByPrimaryKey(request.getSessionId());
        if (null == imSessionInfo) {
            throw new ApiException("找不到对应的会话信息{" + request.getSessionId() + "}");
        }
        imSessionInfo.setStatus(YxImSessionStatusEnum.FINISH.getCode().byteValue());
        imSessionInfo.setRemark(request.getRemak());
        imSessionInfo.setFinalUserId(request.getServiceUserId());
        imSessionInfo.setFinalTime(new Date());
        int count = imSessionInfoMapper.updateByPrimaryKeySelective(imSessionInfo);
        //结束会话 同步更新客户客服绑定表中的解决状态
        int i= imUserBindInfoMapper.updateSolveStatusBySessionId(request.getSessionId());
        if (count > 0) {
            try {
                //需要做一个标识，让im系统触发给客户发送消息，撤回界面消息
                Map<String, String> mq_message = new HashMap<>();
                mq_message.put("sessionId", String.valueOf(request.getSessionId()));
                mq_message.put("receiveUserId", imSessionInfo.getCustomerId());
                mq_message.put("type",QueueConstants.IM_END_QUEUE);
//                rabbitTemplate.convertAndSend(QueueConstants.IM_END_QUEUE, mq_message);
                stringRedisTemplate.convertAndSend(QueueConstants.IM_ADMIN_NOTIFY, JSON.toJSONString(mq_message));
            }catch (Exception e) {
                log.error("===发送客服主动结束会话到消息队列失败==={}", e);
            }
            return CommonResult.success(count+i);
        }
        return CommonResult.failed();
    }

    @Override
    public CommonPage<ImMonitorListItemResponse> queryMonitorSessionList(ImMonitorListRequest request) {
        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<ImMonitorListItemResponse> list = imSessionInfoMapper.queryMonitorSessionList(request);
        return CommonPage.restPage(list);
    }

    @Override
    public Integer queryMeetingSessionNum() {
        Integer num = imSessionInfoMapper.queryMeetingSessionNum(YxImSessionStatusEnum.CONNECT.getCode());
        return num;
    }

    @Override
    public List<AdminDto> selectName(Integer type) {
        if (null != type) {
            //查询在线客服
            List<AdminDto> adminDtos = imSessionInfoMapper.selectOnlineName();
            String userId = UserUtil.getPrincipal();
            adminDtos = adminDtos.stream().filter(item -> !userId.equals(item.getEmail())).collect(Collectors.toList());
            return adminDtos ;
        }
        //查询所有客服
        return imSessionInfoMapper.selectName();
    }

    @Override
    public CommonPage realTimeServiceData(ImRealTimeServiceDateListRequest request) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String curDate = sdf.format(new Date());
//        List<String> serviceNameList = new ArrayList<>();
//        if (null != request.getGroupId()){
//            serviceNameList = imServiceUserMapper.selectServiceNameByGroupId(request.getGroupId());
//        }
        //查询客服
        List<ImRealTimeServiceDateListResponse> listResponses = imServiceUserMapper.queryOnlineServiceNum(request.getStatus(),request.getGroupId(),request.getCompellation());
        //客服当前连接人数
        List<ImSessionConnectTotalResponse> serviceConnectTotal = imSessionInfoMapper.selectServiceConnectTotal();
//        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        //客服累计连接人数
//        List<ImSessionConnectTotalResponse> imSessionConnectTotalResponses = imSessionInfoMapper.selectServiceHistoryTotal();
        listResponses.stream().forEach(response -> {
            if (null == redisService.get(ImRedisKeyConstant.IM_ONLINE_SERVICE_TIME + curDate + ":" + response.getEmail())){
                response.setSort(1);
                return;
            }
            response.setSort(0);
            response.setEvaluate(0);
            log.info("===response.getEmail()==={}", response.getEmail());
            List<Integer> serviceSessionNum = imSessionInfoMapper.selectEveryServiceSessionNum(response.getEmail());
            log.info("===serviceSessionNum==={}", serviceSessionNum.size());
            //今日该客服当前连接人数
            List<ImSessionConnectTotalResponse> curService = serviceConnectTotal.stream().filter(s -> response.getEmail().equals(s.getServiceId())).collect(Collectors.toList());
            response.setCurNum(CollectionUtils.isEmpty(curService) ? 0 : curService.get(0).getNum());
            //今日该客服累计连接人数
//            List<ImSessionConnectTotalResponse> imSessionConnectTotalResponseStreams = imSessionConnectTotalResponses.stream().filter(s -> s.getServiceId().equals(response.getEmail())).collect(Collectors.toList());
//            response.setHistoryNum(CollectionUtils.isEmpty(imSessionConnectTotalResponseStreams) ? 0 : imSessionConnectTotalResponseStreams.get(0).getNum());
            response.setHistoryNum(CollectionUtils.isEmpty(serviceSessionNum) ? 0 : serviceSessionNum.size());
            //首次登陆时间
            response.setFirstOnlineTime(redisService.get(ImRedisKeyConstant.IM_ONLINE_SERVICE_TIME + curDate + ":" + response.getEmail()));
            //当前状态持续时间
            Long countByOn = 0L;
            Long countByRest = 0L;
            Long countByOff = 0L;
            if (1 == response.getStatus()){
                //每次设置在线时间
                String onLineTime = redisService.get(ImRedisKeyConstant.IM_ONLINE_SERVICE_TIME_EVERY_TIME + curDate + ":" + response.getEmail());
                countByOn = (System.currentTimeMillis() - Long.parseLong(StringUtils.isEmpty(onLineTime) ? "0" : onLineTime))/1000;
            }else if (2 == response.getStatus()){
                //每次设置小休时间
                String restTime = redisService.get(ImRedisKeyConstant.IM_REST_SERVICE_TIME_EVERY_TIME + curDate + ":" + response.getEmail());
                countByRest = (System.currentTimeMillis() - Long.parseLong(StringUtils.isEmpty(restTime) ? "0" : restTime))/1000;
            }else if (3 == response.getStatus()){
                //每次设置离线时间
                String offLineTime = redisService.get(ImRedisKeyConstant.IM_SERVICE_UNLINE_TIME_EVERY_TIME + curDate + ":" + response.getEmail());
                countByOff = (System.currentTimeMillis() - Long.parseLong(StringUtils.isEmpty(offLineTime) ? "0" : offLineTime))/1000;
            }
            //在线总时长
            String onlineTimeStr = redisService.get(ImRedisKeyConstant.IM_SERVICE_TIME + curDate + ":" + response.getEmail());
            long l1 = Long.parseLong(StringUtils.isEmpty(onlineTimeStr) ? "0" : onlineTimeStr)/1000 + countByOn;
            response.setOnlineTime(l1);
            response.setNewOnlineTime(secondToTime(l1));
            //小休总时长
            String restTimeStr = redisService.get(ImRedisKeyConstant.IM_REST_TIME + curDate + ":" + response.getEmail());
            long l2 = Long.parseLong(StringUtils.isEmpty(restTimeStr) ? "0" : restTimeStr)/1000 + countByRest;
            response.setRestTime(l2);
            response.setNewRestTime(secondToTime(l2));
            //离线总时长
            String offlineTimeStr = redisService.get(ImRedisKeyConstant.IM_SERVICE_OFFLINE_TIME + curDate + ":" + response.getEmail());
            long l3 = Long.parseLong(StringUtils.isEmpty(offlineTimeStr) ? "0" : offlineTimeStr)/1000 + countByOff;
            response.setUnlineTime(l3);
            response.setNewUnlineTime(secondToTime(l3));
        });
        CommonPage page = CommonPage.restPage(listResponses);
        page.setList((List) page.getList().stream().sorted(Comparator.comparing(ImRealTimeServiceDateListResponse::getStatus).thenComparing(ImRealTimeServiceDateListResponse::getSort)).collect(Collectors.toList()));
        return page;
    }

    /**
     * 返回日时分秒
     * @param second
     * @return
     */
    private static String secondToTime(long second) {

        long days = second / 86400;//转换天数
        second = second % 86400;//剩余秒数
        long hours = second / 3600;//转换小时数
        second = second % 3600;//剩余秒数
        long minutes = second / 60;//转换分钟
        second = second % 60;//剩余秒数
        if (0 < days){
            return days + "天，"+hours+"小时，"+minutes+"分，"+second+"秒";
        }else if (0 == days && 0 < hours){
            return hours+"小时，"+minutes+"分，"+second+"秒";
        }else if (0 == days && 0 == hours && 0 < minutes){
            return minutes+"分，"+second+"秒";
        }else if (0 == days && 0 == hours && 0 == minutes && 0 < second){
            return second+"秒";
        }else {
            return "0";
        }
    }



    @Override
    public CommonPage<ImWorkReportListResponse> workReport(ImWorkReportListRequest request) {
        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        //获取当前月的日期
        List<String> dayByMonth = getDayByMonth();
        //判断是否有时间的查询条件
        if (!StringUtils.isEmpty(request.getStartTime()) && !StringUtils.isEmpty(request.getEndTime())){
            dayByMonth = getDays(request.getStartTime(),request.getEndTime());
        }else if (!StringUtils.isEmpty(request.getStartTime()) && StringUtils.isEmpty(request.getEndTime())){
            dayByMonth = getDays(request.getStartTime(),dayByMonth.get(dayByMonth.size()-1));
        }else if (StringUtils.isEmpty(request.getStartTime()) && !StringUtils.isEmpty(request.getEndTime())){
            dayByMonth= getDays(dayByMonth.get(0),request.getEndTime());
        }
        //查询
        List<ImWorkReportListResponse> listResponses = imSessionInfoMapper.workReport(request);
        List<String> finalDayByMonth = dayByMonth;
        listResponses.forEach(item -> {
            item.setActiveNum(0);//主动发起量
            item.setLeaveMessageNum(0);//留言处理量
            // 这里要实现所有时间的累加
            AtomicReference<Integer> restNum = new AtomicReference<>(0); //小休次数
            AtomicReference<Integer> offlineNum = new AtomicReference<>(0); //离开次数
            AtomicReference<Long> onlineTime = new AtomicReference<>(0L); //累计在线时长
            AtomicReference<Long> restTime = new AtomicReference<>(0L); //累计小休时长
            AtomicReference<Long> offLineTime = new AtomicReference<>(0L); //累计离线时长
            finalDayByMonth.forEach(day ->{
                String dayRest = redisService.get(ImRedisKeyConstant.IM_SERVICE_REST_NUM + day + ":" + item.getEmail());
                Integer s = Integer.valueOf(StringUtils.isEmpty(dayRest) ? "0" : dayRest);
                restNum.set(restNum.get() + s);

                String dayOffLine = redisService.get(ImRedisKeyConstant.IM_SERVICE_UNLINE_NUM + day + ":" + item.getEmail());
                Integer s1 = Integer.valueOf(StringUtils.isEmpty(dayOffLine) ? "0" : dayOffLine);
                offlineNum.set(offlineNum.get() + s1);

                String dayServiceTime = redisService.get(ImRedisKeyConstant.IM_SERVICE_TIME + day + ":" + item.getEmail());
                Long s2 = Long.parseLong(StringUtils.isEmpty(dayServiceTime) ? "0" : dayServiceTime) /1000;
                onlineTime.set(onlineTime.get() + s2);

                String dayRestTime = redisService.get(ImRedisKeyConstant.IM_REST_TIME + day + ":" + item.getEmail());
                Long s3 = Long.parseLong(StringUtils.isEmpty(dayRestTime) ? "0" : dayRestTime) /1000;
                restTime.set(restTime.get() + s3);

                String dayOffLineTime = redisService.get(ImRedisKeyConstant.IM_SERVICE_OFFLINE_TIME + day + ":" + item.getEmail());
                Long s4 = Long.parseLong(StringUtils.isEmpty(dayOffLineTime) ? "0" : dayOffLineTime) /1000;
                offLineTime.set(offLineTime.get() + s4);
            });
            item.setRestNum(restNum.get());//小休次数
            item.setOfflineNum(offlineNum.get());//离开次数
            item.setOnlineTime(onlineTime.get());//累计在线时长
            item.setOnlineTimeStr(secondToTime(onlineTime.get()));
            item.setRestTime(restTime.get());//累计小休时长
            item.setRestTimeStr(secondToTime(restTime.get()));
            item.setUnlineTime(offLineTime.get());//累计离线时长
            item.setUnlineTimeStr(secondToTime(offLineTime.get()));
            Long sessionAvtTime = getSessionAvtTime(item.getEmail());
            item.setAvgMessageTime(sessionAvtTime);//平均会话时长(单位：秒)
            item.setAvgMessageTimeStr(secondToTime(sessionAvtTime));

            String inviteRate = imSessionInfoMapper.findServiceInviteRate(item.getEmail());
            String scoreRate = imSessionInfoMapper.findServiceScoreRate(item.getEmail());
//            String scoreRateStr = "满意";
//            if (scoreRate>=5){
//                scoreRateStr = "非常满意";
//            }
//            if (scoreRate<5 && scoreRate>=4){
//                scoreRateStr = "满意";
//            }
//            if (scoreRate<4 && scoreRate>=3){
//                scoreRateStr = "一般";
//            }
//            if (scoreRate<3 && scoreRate>=2){
//                scoreRateStr = "不满意";
//            }
//            if (scoreRate<2){
//                scoreRateStr = "非常不满意";
//            }
            item.setInviteRate(inviteRate+"%");
            item.setScoreRate(scoreRate);

//            //小休次数
//            String restNum = redisService.get(ImRedisKeyConstant.IM_SERVICE_REST_NUM_TOTAL + item.getId());
//            //离开次数
//            String offlineNum = redisService.get(ImRedisKeyConstant.IM_SERVICE_UNLINE_NUM_TOTAL + item.getId());
//
//            item.setRestNum(Integer.parseInt(StringUtils.isEmpty(restNum) ? "0" : restNum));//小休次数
//            item.setOfflineNum(Integer.parseInt(StringUtils.isEmpty(offlineNum) ? "0" : offlineNum));//离开次数
//            //累计在线时长
//            String onlineTime = redisService.get(ImRedisKeyConstant.IM_SERVICE_ONLINE_TOTAL + item.getId());
//            item.setOnlineTime(Integer.parseInt(StringUtils.isEmpty(onlineTime) ? "0" : onlineTime));//累计在线时长(单位：秒)
//            //累计小休时长
//            String restTime = redisService.get(ImRedisKeyConstant.IM_SERVICE_REST_TOTAL + item.getId());
//            item.setRestTime(Integer.parseInt(StringUtils.isEmpty(restTime) ? "0" : restTime));//累计小休时长(单位：秒)
//            //当天的离线时长
//            item.setUnlineTime(0L);//累计离线时长(单位：秒)
        });
        return CommonPage.restPage(listResponses);
    }

    /**
     * 计时客服会话平均时长
     * @return
     */
    public Long getSessionAvtTime(String userId) {
        String  avtTimeStr = redisService.get("admin:im:getSessionAvtTime:"+userId);
        if (org.apache.commons.lang3.StringUtils.isNotBlank(avtTimeStr)){
            return Long.parseLong(avtTimeStr);
        }
        ImSessionInfoExample imSessionInfoExample = new ImSessionInfoExample();
        imSessionInfoExample.createCriteria().andServiceIdEqualTo(userId);
        List<ImSessionInfo> sessionInfos = imSessionInfoMapper.selectByExample(imSessionInfoExample);

        List<Long> results = new LinkedList<>();
        sessionInfos.stream().forEach(item -> {
            ImMessageInfoExample imMessageInfoExample = new ImMessageInfoExample();
            imMessageInfoExample.createCriteria().andSessionIdEqualTo(item.getId());
            imMessageInfoExample.setOrderByClause("create_time desc limit 1");
            List<ImMessageInfo> endList = imMessageInfoMapper.selectByExample(imMessageInfoExample);
            if (CollectionUtils.isEmpty(endList)) {
                return;
            }
            ImMessageInfo endObj = endList.get(0);

            imMessageInfoExample.setOrderByClause("create_time limit 1");
            List<ImMessageInfo> startList = imMessageInfoMapper.selectByExample(imMessageInfoExample);
            if (CollectionUtils.isEmpty(startList)) {
                return;
            }
            ImMessageInfo startObj = startList.get(0);

            results.add((endObj.getCreateTime().getTime() - startObj.getCreateTime().getTime()) / 1000);
        });
        Long result = 0L;
        if (CollectionUtils.isEmpty(results)) {
            return result;
        }
        for (int i = 0; i < results.size(); i++) {
            result += results.get(i);
        }
        Long time = result / results.size();
        redisService.set("admin:im:getSessionAvtTime:"+userId,String.valueOf(time));
        redisService.expire("admin:im:getSessionAvtTime:"+userId,3600*12);
        return time;
    }


    /**
     * 根据客户id获取所有会话记录
     * @param customerId
     * @return
     */
    @Override
    public List<ImSessionInfo> querySessionListByCustomerId(String customerId) {
        ImSessionInfoExample example = new ImSessionInfoExample();
        example.createCriteria().andCustomerIdEqualTo(customerId);
        example.setOrderByClause("createTime asc");
        List<ImSessionInfo> list = imSessionInfoMapper.selectByExample(example);
        return list;
    }

    @Override
    public List<ImSessionInfo> querySessionListByServiceId(String serviceId, Integer status) {
        ImSessionInfoExample example = new ImSessionInfoExample();
        example.createCriteria().andServiceIdEqualTo(serviceId).andStatusEqualTo(status.byteValue());
        List<ImSessionInfo> list = imSessionInfoMapper.selectByExample(example);
        return list;
    }

    /**
     * 查看客服是否有沟通中的会话
     * @param userId
     * @return
     */
    @Override
    public List<ImSessionInfoDto> selectSessionByUserId(String userId) {
        return imSessionInfoMapper.selectSessionByUserId(userId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateSessionByCustomerId(String customerId,String serviceId,Integer leaveMsgId) {
        int count = imSessionInfoMapper.updateSessionByCustomerId(customerId, serviceId);
        Assert.isTrue(count>0,"重新发起会话失败");
        if (leaveMsgId!=null){
            ImLeaveMsg record = new ImLeaveMsg();
            record.setId(leaveMsgId);
            record.setFinshType("客服发起会话");
            imLeaveMsgService.updateFinshType(record);
        }

    }

    @Override
    public Map<String, Integer> findServiceStatusInfo() {
        Map<String, Integer> map = Maps.newHashMap();
        int total = 0;
        int online = 0;
        int rest =0;
        int offline=0;

        List<ImRealTimeServiceDateListResponse> listResponses = imServiceUserMapper.queryOnlineServiceNum(null,null,null);
        if (!CollectionUtils.isEmpty(listResponses)){
            for (ImRealTimeServiceDateListResponse item:listResponses){
                if (item.getStatus() ==1){
                    online++;
                }
                if (item.getStatus() ==2){
                    rest++;
                }
                if (item.getStatus() ==3){
                    offline++;
                }
            }
            total = listResponses.size();
        }
        map.put("total",total);
        map.put("online",online);
        map.put("rest",rest);
        map.put("offline",offline);
        return map;
    }

    @Override
    public int findToDayCount() {
        return imSessionInfoMapper.findToDayCount();
    }

//    public static void main(String[] args) {
//        Calendar cal = Calendar.getInstance();
//        int day = cal.get(Calendar.DATE);
//        int month = cal.get(Calendar.MONTH) + 1;
//        int year = cal.get(Calendar.YEAR);
//        int dow = cal.get(Calendar.DAY_OF_WEEK);
//        int dom = cal.get(Calendar.DAY_OF_MONTH);
//        int doy = cal.get(Calendar.DAY_OF_YEAR);
//
//        System.out.println("当期时间: " + cal.getTime());
//        System.out.println("日期: " + day);
//        System.out.println("月份: " + month);
//        System.out.println("年份: " + year);
//        System.out.println("一周的第几天: " + dow);  // 星期日为一周的第一天输出为 1，星期一输出为 2，以此类推
//        System.out.println("一月中的第几天: " + dom);
//        System.out.println("一年的第几天: " + doy);
//    }

//    public static void main(String[] args) {
//        List<String> dayByMonth = getDayByMonth();
//        dayByMonth.forEach(d ->{
//            System.out.println(d);
//        });
//        System.out.println("----------------------------------------");
//        List<String> dates = dateToWeek();
//        dates.forEach(date -> {
//            System.out.println(date);
//        });
//    }

    /**
     * 获取当前月到当天的日期
     */
    public static List<String> getDayByMonth() {
        Calendar cal = Calendar.getInstance();
        int dayParam = cal.get(Calendar.DATE);
        int monthParam = cal.get(Calendar.MONTH);
        int yearParam = cal.get(Calendar.YEAR);
        List list = new ArrayList();
        Calendar aCalendar = Calendar.getInstance(Locale.CHINA);
        aCalendar.set(yearParam, monthParam, 1);
        int year = aCalendar.get(Calendar.YEAR);//年份
        int month = aCalendar.get(Calendar.MONTH) + 1;//月份
//        int day = aCalendar.getActualMaximum(Calendar.DATE);当前月份的天数
        for (int i = 1; i <= dayParam; i++) {
            String aDate = null;
            if (month < 10 && i < 10) {
                aDate = year + "-0" + month + "-0" + i;
            }
            if (month < 10 && i >= 10) {
                aDate = year + "-0" + month + "-" + i;
            }
            if (month >= 10 && i < 10) {
                aDate = year + "-" + month + "-0" + i;
            }
            if (month >= 10 && i >= 10) {
                aDate = year + "-" + month + "-" + i;
            }
            list.add(aDate);
        }
        return list;
    }

    public static void main(String[] args) {
        List<String> days = getDayByMonth();
        days.forEach(item -> System.out.println(item));
    }

    /**
     * 获取当前星期的年月日
     */
    public static List<String> dateToWeek() {
        Date mdate = new Date();
        int b = mdate.getDay();
        Date fdate;
        List<String> list = new ArrayList<>();
        Long fTime = mdate.getTime() - b * 24 * 3600000;
        for (int a = 1; a <= 7; a++) {
            fdate = new Date();
            fdate.setTime(fTime + (a * 24 * 3600000));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String curDate = sdf.format(fdate);
            list.add(curDate);
        }
        return list;
    }

//    public static void main(String[] args) {
//        System.out.println(getDays("2018-06-28", "2018-07-03"));
//    }

    /**
     * 获取两个日期之间的所有日期
     *
     * @param startTime
     *            开始日期
     * @param endTime
     *            结束日期
     * @return
     */
    public static List<String> getDays(String startTime, String endTime) {

        // 返回的日期集合
        List<String> days = new ArrayList<String>();

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);

            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);

            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束)
            while (tempStart.before(tempEnd)) {
                days.add(dateFormat.format(tempStart.getTime()));
                tempStart.add(Calendar.DAY_OF_YEAR, 1);
            }

        } catch (ParseException e) {
            e.printStackTrace();
        }

        return days;
    }
}
